#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "config.h"
#ifdef X11_KBDDRIVER
#include <X11/Xlib.h>
#include <X11/keysymdef.h>
#include <X11/keysym.h>
#include "aalib.h"
#include "aaint.h"
#include "aaxint.h"
#define dr (d->pixmapmode?d->pi:d->wi)

static int X_init(aa_context * c, int mode)
{
	struct xdriverdata *d=c->driverdata;
	if(c->driver!=&X11_d) return 0;
	d->attr.event_mask |= StructureNotifyMask | KeyPressMask | (mode & AA_SENDRELEASE ? KeyReleaseMask : 0);
	XSelectInput(d->dp, d->wi, d->attr.event_mask);
	aa_recommendlowmouse("X11");
	return 1;
}
static void X_uninit(aa_context * c)
{
	struct xdriverdata *d=c->driverdata;
	d->attr.event_mask &= ~(KeyPressMask | KeyReleaseMask);
	XSelectInput(d->dp, d->wi, d->attr.event_mask);
}
static int decodekey(XEvent * ev)
{
	KeySym ksym;
	char name[256];
	switch (ksym = XLookupKeysym(&ev->xkey, ev->xkey.state)) {
	case XK_Left:
		return (AA_LEFT);
	case XK_Right:
		return (AA_RIGHT);
	case XK_Up:
		return (AA_UP);
	case XK_Down:
		return (AA_DOWN);
	case XK_Escape:
		return (AA_ESC);
	case XK_space:
		return (' ');
	case XK_Return:
#ifdef XK_cr
	case XK_cr:
#endif
		return (13);
	case XK_BackSpace:
	case XK_Delete:
		return (AA_BACKSPACE);
	}
	name[XLookupString(&ev->xkey,name,256,&ksym,NULL)]=0;
	if(strlen(name)!=1) return (AA_UNKNOWN+ksym);
	return name[0];
}
extern int __X_mousex, __X_mousey, __X_buttons;
static int X_getchar(aa_context * c, int wait)
{
	struct xdriverdata *d=c->driverdata;
	while (1) {
		XEvent ev;
		if (!wait && !XPending(d->dp))
			return AA_NONE;
		XNextEvent(d->dp, &ev);
		switch (ev.type) {
		case ButtonPress:
			ev.xbutton.state |= 1 << (ev.xbutton.button + 7);
			goto skip;
		case ButtonRelease:
			ev.xbutton.state &= ~(1 << (ev.xbutton.button + 7));
		  skip:;
		case MotionNotify:
			__X_mousex = ev.xbutton.x;
			__X_mousey = ev.xbutton.y;
			__X_buttons = ev.xbutton.state;
			return (AA_MOUSE);
		case Expose:
			XSync(d->dp, 0);
			__aa_X_redraw(c);
			break;
		case ConfigureNotify:
			if (__aa_X_getsize(c,d))
				return (AA_RESIZE);
			break;
		case KeyPress:
			return (decodekey(&ev));
		case KeyRelease:
			return (decodekey(&ev) | AA_RELEASE);

		}
	}
}

__AA_CONST struct aa_kbddriver kbd_X11_d =
{
	"X11", "X11 keyboard driver 1.0",
	AA_SENDRELEASE,
	X_init,
	X_uninit,
	X_getchar,
};
#endif
